home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-19 | 24.8 KB | 1,090 lines |
-
- /*
- * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
- *
- * (b) If this Sample Code is distributed as part of the Display PostScript
- * System Software Development Kit from Adobe Systems Incorporated,
- * then this copy is designated as Development Software and its use is
- * subject to the terms of the License Agreement attached to such Kit.
- *
- * (c) If this Sample Code is distributed independently, then the following
- * terms apply:
- *
- * (d) This file may be freely copied and redistributed as long as:
- * 1) Parts (a), (d), (e) and (f) continue to be included in the file,
- * 2) If the file has been modified in any way, a notice of such
- * modification is conspicuously indicated.
- *
- * (e) PostScript, Display PostScript, and Adobe are registered trademarks of
- * Adobe Systems Incorporated.
- *
- * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
- * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
- * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
- * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
- * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
- * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
- * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
- * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
- * OF THIRD PARTY RIGHTS.
- */
-
- /*
- * DrawingView.m
- *
- * This view represents the page that the image is drawn onto.
- *
- * An offscreen buffer, bufferId, is used to draw into and then
- * this buffer is composited onscreen. This technique allows for the
- * separation of the static drawing from the temporal drawing (modal
- * loop redrawing and control point display). The static drawing takes
- * place in the buffer while the temporal drawing takes place in this view.
- * The static drawing is stuff that is complex and that will stay around for
- * a while. Saving this drawing in a buffer elimates having to redraw it
- * for something simple like drawing a control point or something.
- * (The bufferId is the content view of a plain window the size of this view);
- *
- * Version: 2.0
- * Author: Ken Fromm
- * History:
- * 03-17-91 Added this comment, fixed the preview exporting
- * section.
- */
-
- #import "DrawingView.h"
- #import "Document.h"
- #import "GraphicImport.h"
- #import "SaveAsPanel.h"
- #import "epsf.h"
-
- #import "DrawingViewWraps.h"
-
- #import <appkit/Cell.h>
- #import <appkit/ClipView.h>
- #import <appkit/Matrix.h>
- #import <appkit/NXCursor.h>
- #import <appkit/NXImage.h>
- #import <appkit/NXBitmapImageRep.h>
- #import <appkit/Text.h>
- #import <appkit/nextstd.h>
-
- #import <dpsclient/dpsclient.h>
- #import <dpsclient/wraps.h>
- #import <math.h>
-
- extern char ControlFont[ ];
-
- extern const NXRect DefaultWindowRect;
-
- static char EpsfProcSet[] = "EPSF_Illustrator_abbrev 0 0";
-
- void compositeBuffer(int gstate, const NXRect *srce, const NXPoint *dest, int op)
- {
- PScomposite(NX_X(srce), NX_Y(srce), NX_WIDTH(srce), NX_HEIGHT(srce),
- gstate, dest->x, dest->y, op);
- }
-
- /*
- * The buffer is used to prevent unnecessary drawing by
- * retaining the image offscreen.
- *
- * Create a plain window the size of the rectangle passed in and
- * then insert a view into the window as a subview.
- */
- static id createBuffer(const NXSize *size)
- {
- id buffer, window;
-
- NXRect contRect;
-
- contRect.origin.x = contRect.origin.y = 0;
- contRect.size = *size;
- window = [Window newContent:&contRect
- style:NX_PLAINSTYLE
- backing:NX_RETAINED
- buttonMask:0
- defer:NO] ;
-
- buffer = [[[View newFrame:&contRect] allocateGState] setClipping:NO];
- [[window setContentView:buffer ] free];
-
- [ window display];
-
- return buffer;
- }
-
- @implementation DrawingView
-
- +newFrame:(const NXRect *) frameRect
- {
- self = [super newFrame:frameRect];
- [[self allocateGState] setClipping:NO];
-
- bufferId = createBuffer(&frameRect->size);
-
- return self;
- }
-
- - free
- {
- [graphicId free];
-
- return [super free];
- }
-
- - buffer
- {
- return bufferId;
- }
-
- - image
- {
- return imageId;
- }
-
- - (float) controlPointSize
- {
- return FONTSIZE;
- }
-
- - resetCursorRects
- {
- [self addCursorRect:&bounds cursor:[NXApp cursor]];
-
- return self;
- }
-
- /*
- * This method copies the PostScript code for the graphics and writes it to the
- * stream passed in. Includes the preview image when appropriate.
- */
- - writePSToStream:(NXStream *) stream
- {
- id nximageId;
-
- NXRect bbox;
-
- if (stream)
- {
- nximageId = NULL;
- imageId = NULL;
-
- [graphicId getBounds:&bbox];
- if ([[SaveAsPanel new] format] == SAVE_EPSPREVIEW)
- {
- nximageId = [[NXImage alloc] initSize:&bbox.size];
- [nximageId useCacheWithDepth:NX_TwoBitGrayDepth];
- if ([nximageId lockFocus])
- {
- PStranslate(-bbox.origin.x, -bbox.origin.y);
- PSsetgray(NX_WHITE);
- NXRectFill(&bbox);
- [graphicId drawObject:&bbox withFlags:NOFLAGS inView:self];
-
- imageId = [[NXBitmapImageRep alloc] initData:NULL fromRect:&bbox];
- [nximageId unlockFocus];
- }
- }
-
- [self copyPSCodeInside:&bbox to:stream];
-
- [nximageId free];
- [imageId free];
- imageId = NULL;
- }
-
- return self;
- }
-
- /* Deletes the epsf object if it is selected. */
- - delete:sender
- {
- float knobsize;
-
- NXRect rect;
-
- if ([graphicId selected])
- {
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&rect];
- NXInsetRect(&rect, knobsize, knobsize);
- [graphicId free];
- graphicId = NULL;
-
- [self display:&rect :1];
- }
-
- return self;
- }
-
- /*
- * Constrain the point within the view. An offset is needed because when
- * an object is moved, it is often grabbed in the center of the object. If the
- * lower left offset and the upper right offset were not included then part of
- * the object could be moved off of the view. (In some applications, that might
- * be allowed but in this one the object is constrained to always lie in the
- * page.)
- */
- - constrainPoint:(NXPoint *)aPt withOffset:(const NXSize*)llOffset :(const NXSize*)urOffset
- {
- float margin;
-
- NXPoint viewMin, viewMax;
-
- margin = ceil(FONTSIZE/2);
-
- viewMin.x = bounds.origin.x + llOffset->width + margin;
- viewMin.y = bounds.origin.y + llOffset->height + margin;
-
- viewMax.x = bounds.origin.x + bounds.size.width - urOffset->width - margin;
- viewMax.y = bounds.origin.y + bounds.size.height - urOffset->height - margin;
-
- aPt->x = MAX(viewMin.x, aPt->x);
- aPt->y = MAX(viewMin.y, aPt->y);
-
- aPt->x = MIN(viewMax.x, aPt->x);
- aPt->y = MIN(viewMax.y, aPt->y);
-
- return self;
- }
-
- /*
- * Constrain a rectangle within the view.
- */
- - constrainRect:(NXRect *)aRect
- {
- float margin;
-
- NXPoint viewMin, viewMax;
-
- margin = ceil(FONTSIZE/2);
-
- viewMin.x = bounds.origin.x + margin;
- viewMin.y = bounds.origin.y + margin;
-
- viewMax.x = bounds.origin.x + bounds.size.width - aRect->size.width - margin;
- viewMax.y = bounds.origin.y + bounds.size.height - aRect->size.height - margin;
-
- aRect->origin.x = MAX(viewMin.x, aRect->origin.x);
- aRect->origin.y = MAX(viewMin.y, aRect->origin.y);
-
- aRect->origin.x = MIN(viewMax.x, aRect->origin.x );
- aRect->origin.y = MIN(viewMax.y, aRect->origin.y);
-
- return self;
- }
-
- /*
- * Redraws the graphic. The image from the buffer is composited
- * into the window and then the changed object is drawn atop the
- * old image. A copy of the image is necessary because if the
- * window were to allow scrolling the buffer would also have to be
- * scrolled. Were this to happen the old image might have to be redrawn.
- * As a result, a copy is created and the changes performed on the
- * copy. Care is taken to limit the amount of area that must be
- * composited and redrawn.
- *
- * Even though scrolling is not allowed in this instance, a copy is
- * created anyways.
- */
- - redrawObject:(int) pt_num
- {
- id copyId;
-
- BOOL tracking,
- dirtyFlag = NO;
-
- int old_mask;
-
- float knobsize;
-
- NXPoint pt, pt_last, pt_old, delta;
-
- NXRect rect_now, rect_start, rect_last;
-
- NXEvent *event;
-
- /*
- * The freeTemp method is messaged at the bottom so as not to free
- * the shared items.
- */
- copyId = [graphicId copy];
-
- knobsize = -[self controlPointSize];
- [copyId getBounds:&rect_start];
- NXInsetRect(&rect_start, knobsize, knobsize);
-
- rect_now = rect_last = rect_start;
-
- [copyId getPoint:pt_num :&pt_last];
- pt_old = pt_last;
-
- old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
- if (event->type != NX_MOUSEUP)
- {
- tracking = YES;
- while (tracking)
- {
- pt = pt_old = event->location;
-
- [self convertPoint:&pt fromView:nil];
- [copyId constrainPoint:&pt forPtNum:&pt_num
- inRect:&bounds withFlags:event->flags];
-
- delta.x = pt.x - pt_last.x;
- delta.y = pt.y - pt_last.y;
-
- if (delta.x || delta.y)
- {
- dirtyFlag = YES;
- /* Change the point location and get the new bounds. */
- [copyId setPoint:pt_num :&delta];
- [copyId getBounds:&rect_now];
- NXInsetRect(&rect_now, knobsize, knobsize);
-
- /* Composite the old image and then redraw the new one. */
- compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY);
- [self drawObject:copyId forRect:&rect_now withFlags:REDRAWFLAG];
- [self drawControl:copyId forRect:&rect_now withFlags:NOFLAGS];
-
- /* Sync up the drawing so it proceeds a little smoother. */
- [window flushWindow];
- NXPing();
-
- rect_last = rect_now;
- pt_last = pt;
- }
-
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|
- NX_MOUSEDRAGGEDMASK];
- tracking = (event->type != NX_MOUSEUP);
- }
- }
- [window setEventMask:old_mask];
-
- [graphicId freeTemp];
- graphicId = copyId;
-
- if (dirtyFlag)
- {
- /*
- * The view has already been focused and we know what
- * has to be redrawn so call drawSelf:: instead of display
- */
- NXUnionRect(&rect_last, &rect_start);
- [self drawSelf:&rect_start :1];
- [window flushWindow];
- NXPing();
- }
-
- return self;
- }
-
- /*
- * Moves the selected objects by performing a translate before drawing
- * the objects. This approach is used because the objects are drawn
- * into windows and drawing simply means compositing the windows.
- *
- * The offsets constrain the selected object to stay within the dimensions
- * of the view.
- */
- - moveObject:(NXEvent *)event
- {
- BOOL tracking,
- dirtyFlag = NO;
-
- int old_mask;
-
- float knobsize;
-
- NXSize llOffset, urOffset;
-
- NXPoint pt, pt_last, pt_old, delta;
-
- NXRect rect_now, rect_start, rect_last;
-
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&rect_start];
- NXInsetRect(&rect_start, knobsize, knobsize);
- rect_now = rect_last = rect_start;
-
- pt_last = pt_old = event->location;
- [self convertPoint:&pt_last fromView:nil];
-
- /* Calculate where the mouse point falls relative to the object. */
- llOffset.width = pt_last.x - rect_start.origin.x;
- llOffset.height = pt_last.y - rect_start.origin.y;
- urOffset.width = rect_start.origin.x + rect_start.size.width - pt_last.x;
- urOffset.height = rect_start.origin.y + rect_start.size.height - pt_last.y;
-
- /* Return nil if the the mouse was not dragged. */
- old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
- if (event->type != NX_MOUSEUP)
- {
- tracking = YES;
- while (tracking)
- {
- pt = pt_old = event->location;
-
- [self convertPoint:&pt fromView:nil];
- [self constrainPoint:&pt withOffset:&llOffset :&urOffset];
- [self constrainPoint:&pt_last withOffset:&llOffset :&urOffset];
- delta.x = pt.x - pt_last.x;
- delta.y = pt.y - pt_last.y;
-
- if (delta.x || delta.y)
- {
- dirtyFlag = YES;
- NXOffsetRect(&rect_now, delta.x, delta.y);
- [self constrainRect:&rect_now];
-
- /*
- * Composite the old image into the window and then
- * translate the user space and draw the graphicId object.
- */
- compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY);
- PSgsave();
- PStranslate(rect_now.origin.x - rect_start.origin.x,
- rect_now.origin.y - rect_start.origin.y);
- [self drawObject:graphicId forRect:&rect_start withFlags:MOVEFLAG];
- [self drawControl:graphicId forRect:&rect_start
- withFlags:NOFLAGS];
- PSgrestore();
-
- [window flushWindow];
- NXPing();
-
- rect_last = rect_now;
- pt_last = pt;
- }
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|
- NX_MOUSEDRAGGEDMASK];
-
- tracking = (event->type != NX_MOUSEUP);
- }
-
- if (dirtyFlag)
- {
- delta.x = rect_now.origin.x - rect_start.origin.x;
- delta.y = rect_now.origin.y - rect_start.origin.y; [graphicId moveAll:&delta];
-
- /*
- * The view has already been focused and we know what
- * has to be redrawn so call drawSelf:: instead of display
- */
- NXUnionRect(&rect_now, &rect_start);
- [self drawSelf:&rect_start :1];
- [window flushWindow];
- NXPing();
- }
- }
- [window setEventMask:old_mask];
-
- return self;
- }
-
- /* Check to see whether a control point has been hit. */
- - checkControl:(const NXPoint *) p :(int *) pt_num
- {
- NXRect hitRect;
-
- NXSetRect(&hitRect, p->x - HITSETTING/2, p->y - HITSETTING/2, HITSETTING, HITSETTING);
-
- return [graphicId hitControl:&hitRect :pt_num forSize:[self controlPointSize]];
- }
-
- /*
- * Check to see whether the epsf object has been hit. Return it if yes.
- */
- - checkObject:(const NXPoint *) p
- {
- UPath *hitPoint;
-
- /* Bounding Box */
- hitPoint = [NXApp hitPoint];
- hitPoint->pts[0] = floor(p->x - HITSETTING/2);
- hitPoint->pts[1] = floor(p->y - HITSETTING/2);
- hitPoint->pts[2] = ceil(p->x + HITSETTING/2);
- hitPoint->pts[3] = ceil(p->y + HITSETTING/2);
-
- /* Moveto */
- hitPoint->pts[4] = p->x - HITSETTING/2;
- hitPoint->pts[5] = p->y - HITSETTING/2;
-
- /* Rlineto's */
- hitPoint->pts[7] = HITSETTING;
- hitPoint->pts[8] = HITSETTING;
- hitPoint->pts[11] = -HITSETTING;
-
- return [graphicId hitObject:hitPoint];
- }
-
- /*
- * Set the object as selected then draw the control points.
- */
- - selectObject
- {
- float knobsize;
-
- NXRect drawRect;
-
- [graphicId setSelected:YES];
-
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&drawRect];
- NXInsetRect(&drawRect, knobsize, knobsize);
-
- [self drawControl:graphicId forRect:&drawRect withFlags:NOFLAGS];
- [window flushWindow];
-
- return self;
- }
-
- /*
- * Redraw thecontrol points for the occupied portion. The control points
- * are drawn in this view since they can be drawn quickly.
- */
- - deselectObject
- {
- float knobsize;
-
- NXRect drawRect;
-
- [graphicId setSelected:NO];
-
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&drawRect];
- NXInsetRect(&drawRect, knobsize, knobsize);
-
- [self drawControl:graphicId forRect:&drawRect withFlags:CLEARFLAG];
- [window flushWindow];
-
- return self;
- }
-
- /*
- * Test for a mouse down hit on either the control points or the object.
- */
- - testObject:(NXEvent *)event
- {
- int pt_num;
-
- NXPoint p;
-
- p = event->location;
- [self convertPoint:&p fromView:nil];
- [self lockFocus];
- if ([graphicId selected])
- {
- if ([self checkControl:&p :&pt_num])
- [self redrawObject:pt_num];
- else if ([self checkObject:&p])
- [self moveObject:event];
- else
- [self deselectObject];
- }
- else if ([self checkObject:&p])
- [self selectObject];
- [self unlockFocus];
-
- return self;
- }
-
- /*
- * Pass the file name to the factory TIFF or EPS object to create a new
- * instance. If successful then free the previous epsf object.
- */
- - importFile:(const char *) file
- {
- id tempId;
-
- char *end;
-
- NXStream *stream;
-
- if (file)
- {
- end = strrchr(file, '.');
- if (end)
- {
- stream = NXMapFile(file, NX_READONLY);
- if (stream)
- {
- if (strncmp(end, ".tiff", 5) == 0 ||
- strncmp(end, ".ps", 3) == 0 ||
- strncmp(end, ".eps", 4) == 0)
- {
- tempId = [[GraphicImport alloc] initFromStream:stream];
- if (tempId)
- {
- [tempId setFilename:file];
- [self delete:self];
-
- [graphicId free];
- graphicId = tempId;
- [NXApp setOperation:OP_IMPORT];
-
- return self;
- }
- NXCloseMemory(stream, NX_FREEBUFFER);
- }
- else
- Notify("Import Error", "Unable to open file.");
- }
- }
- else
- Notify("Import Error", "Unable to import file. Unrecognized file type.");
- }
-
- return nil;
- }
-
- /*
- * Place the epsId with its upper left corner at p;
- */
- - placeObjectAt:(const NXPoint *) p
- {
- float knobsize;
-
- NXPoint pt;
-
- NXRect rect_draw;
-
- if (graphicId)
- {
- pt = *p;
-
- [graphicId getBounds:&rect_draw];
- pt.y = pt.y - rect_draw.size.height;
- [graphicId setOrigin:&pt];
-
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&rect_draw];
- NXInsetRect(&rect_draw, knobsize, knobsize);
-
- [self display:&rect_draw :1];
- }
-
- return self;
- }
-
- /*
- * Begins the setup for placing an imported file into the document.
- * The object for the file is created and then waits for the mouse
- * down to begin placement and sizing. This method first gets the
- * object and then messages the redrawObject method to draw
- * the subsequent sizing rectangles.
- */
- - importObject:(NXEvent *)event
- {
- float knobsize;
-
- NXPoint p;
-
- NXRect rect_draw;
-
- if (graphicId)
- {
- p = event->location;
- [self convertPoint:&p fromView:nil];
-
- NXSetRect(&rect_draw, p.x, p.y-SIZE_MIN, SIZE_MIN, SIZE_MIN);
- [graphicId setBounds:&rect_draw];
-
- knobsize = -[self controlPointSize];
- [graphicId getBounds:&rect_draw];
- NXInsetRect(&rect_draw, knobsize, knobsize);
-
- [self lockFocus];
- [self drawObject:graphicId forRect:&rect_draw withFlags:REDRAWFLAG];
- [self drawControl:graphicId forRect:&rect_draw withFlags:NOFLAGS];
- [self redrawObject:8];
-
- if ([graphicId error])
- {
- [graphicId getBounds:&rect_draw];
- NXInsetRect(&rect_draw, knobsize, knobsize);
- [graphicId free];
- graphicId = NULL;
-
- [self display:&rect_draw :1];
- }
- else
- [self selectObject];
- [self unlockFocus];
- }
-
- return self;
- }
-
- /*
- * Depending on the current operation, check for selection, zoom or
- * import a file.
- */
- - mouseDown:(NXEvent *)event
- {
- int operation;
-
- operation = [NXApp operation];
- switch (operation)
- {
- case OP_SELECT:
- [self testObject:event];
- break;
- case OP_IMPORT:
- [self importObject:event];
- [NXApp setOperation:OP_SELECT];
- break;
- }
-
- return self;
- }
-
- /*
- * Deletes the epsf object if selected.
- */
- - keyDown:(NXEvent *) event
- {
- if ([NXApp operation] == OP_SELECT &&
- event->data.key.charSet == NX_ASCIISET &&
- event->data.key.charCode == NX_DELETE)
- return [self delete:self];
- else
- return nil;
- }
-
- /*
- * Draw the control points using the user path buffer to hold
- * the data for the xyshow.
- */
- - drawControl:object forRect:(NXRect *)r withFlags:(int)flags
- {
- float knobsize;
-
- NXPoint lastpoint;
-
- NXRect rect;
-
- UPath *upathBuffer;
-
- if (r)
- rect = *r;
- else
- [self getVisibleRect:&rect];
-
- if (flags & CLEARFLAG)
- compositeBuffer([bufferId gState], &rect, &rect.origin, NX_COPY);
-
- if ([object selected])
- {
- lastpoint.x = 0;
- lastpoint.y = 0;
-
- upathBuffer = [NXApp upathBuffer];
- upathBuffer->num_ops = 0;
- upathBuffer->num_pts = 0;
-
- knobsize = [self controlPointSize];
- NXInsetRect(&rect, -knobsize/2, -knobsize/2);
- [object putControlPoints:upathBuffer forRect:&rect :&lastpoint];
-
- upathBuffer->ops[upathBuffer->num_ops] = 0;
- upathBuffer->pts[upathBuffer->num_pts] = 0;
- upathBuffer->pts[upathBuffer->num_pts + 1] = 0;
-
- if (upathBuffer->num_ops > 0)
- {
- PSWSetControlPoints(ControlFont, knobsize, NX_BLACK, 0.15);
- PSWDrawControlPoints(upathBuffer->pts[0], upathBuffer->pts[1],
- &upathBuffer->pts[2], upathBuffer->num_pts, upathBuffer->ops);
- }
- }
-
- return self;
- }
-
- - drawObject:object forRect:(NXRect *)r withFlags:(int) flags
- {
- NXRect rect;
-
- if (r)
- rect = *r;
- else
- [self getVisibleRect:&rect];
-
- [object drawObject:&rect withFlags:flags inView:self];
-
- return self;
- }
-
- /*
- * Fill in the background of the rectangle and then draw the epsf object.
- * If NX_DRAWING, then draw into the buffer and composite it into
- * the window.
- */
- - drawSelf:(NXRect *)r :(int) count
- {
- if (NXDrawingStatus == NX_DRAWING)
- {
- [bufferId lockFocus];
- PSsetgray(NX_WHITE);
- NXRectFill(r);
- }
-
- [self drawObject:graphicId forRect:r withFlags:REFRESHFLAG];
-
- if (NXDrawingStatus == NX_DRAWING && !imageId)
- {
- [bufferId unlockFocus];
- compositeBuffer([bufferId gState], r, &r->origin, NX_COPY);
- [self drawControl:graphicId forRect:r withFlags:NOFLAGS];
- }
-
- return self;
- }
-
- /*
- * This method is only overridden to eliminate during a copy
- * the rectclip and gsave/grestore pairing that results from
- * a lockFocus. These are usually harmless operations but
- * they interfere with trying to produce Illustrator format files.
- */
- - display:(NXRect *)r :(int) count :(BOOL)flag
- {
- if (NXDrawingStatus == NX_COPYING)
- {
- [self drawSelf:r :count];
- DPSFlushContext(DPSGetCurrentContext());
- }
- else
- [super display:r :count :flag];
-
- return self;
- }
-
- - (BOOL)acceptsFirstResponder
- {
- return YES;
- }
-
- /*
- * Used when printing. Returns the global resources used in the document.
- */
- - addResources:(Resource *) resourceDoc
- {
- NXAtom string;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- string = NXUniqueString(EpsfProcSet);
- if (!resourceDoc[RES_PROCSETS].states[RES_PRESENT])
- resourceDoc[RES_PROCSETS].states[RES_PRESENT] = [List new];
-
- [resourceDoc[RES_PROCSETS].states[RES_PRESENT]
- addObjectIfAbsent:(id) string];
-
- if (!resourceDoc[RES_PROCSETS].states[RES_SUPPLIED])
- resourceDoc[RES_PROCSETS].states[RES_SUPPLIED] = [List new];
-
- [resourceDoc[RES_PROCSETS].states[RES_SUPPLIED]
- addObjectIfAbsent:(id) string];
- }
-
- return self;
- }
-
- /*
- * Print the %%DocumentResource comments. A list of the resources is
- * accumulated from the epsf files (only one in this case).
- * The list is then written to the current context.
- */
- - beginResourceComments:(const NXRect *) bbox
- {
- int i, j;
-
- Resource resourceDoc[RES_NUMTYPES];
-
- bzero(&resourceDoc, sizeof(resourceDoc));
- [self addResources:resourceDoc];
- [graphicId addResources:resourceDoc for:(NXRect *) bbox];
-
- for (i = 0; i < RES_NUMTYPES; i++)
- {
- for (j = 0; j < RES_NUMSTATES; j++)
- {
- if (resourceDoc[i].states[j])
- {
- WriteEpsfResource(resourceDoc[i].states[j], i, j);
- [resourceDoc[i].states[j] free];
- }
- }
- }
-
- return self;
- }
-
- /*
- * Write out the necessary information. Overridden to include
- * the fonts from the EPSF files.
- */
- - beginPrologueBBox:(const NXRect *)boundingBox
- creationDate:(const char *)dateCreated
- createdBy:(const char *)anApplication
- fonts:(const char *)fontNames
- forWhom:(const char *)user
- pages:(int)numPages
- title:(const char *)aTitle
- {
- time_t clock;
-
- DPSContext ctxt;
-
- ctxt = DPSGetCurrentContext();
- if (!boundingBox)
- boundingBox = &bounds;
-
- if (!dateCreated)
- {
- clock = time(0);
- dateCreated = ctime(&clock);
- }
-
- if (!anApplication)
- anApplication = [NXApp appName];
-
- if (!user)
- user = (char *) getlogin();
-
- if (numPages <= 0)
- numPages = 1;
-
- if (!aTitle)
- aTitle = [[window delegate] filename];
-
- DPSPrintf(ctxt, "%%!PS-Adobe-2.0 EPSF-1.2\n");
- DPSPrintf(ctxt, "%%%%Creator: %s\n", anApplication);
- DPSPrintf(ctxt, "%%%%For: %s\n", user);
- DPSPrintf(ctxt, "%%%%Title: %s\n", aTitle);
- DPSPrintf(ctxt, "%%%%CreationDate: %s", dateCreated);
- DPSPrintf(ctxt, "%%%%BoundingBox: %d %d %d %d\n", (int) floor(boundingBox->origin.x),
- (int) floor(boundingBox->origin.y),
- (int) ceil(boundingBox->origin.x + boundingBox->size.width),
- (int) ceil(boundingBox->origin.y + boundingBox->size.height));
- if (NXDrawingStatus == NX_COPYING)
- DPSPrintf(ctxt, "%%AI3_TemplateBox: %d %d %d %d\n", 306, 396, 306, 396);
- if (NXDrawingStatus != NX_COPYING)
- DPSPrintf(ctxt, "%%%%Pages: %d\n", numPages);
-
- [self beginResourceComments:boundingBox];
-
- return self;
- }
-
- /*
- * Includes the abbreviated Illustrator proc set so that
- * the eps files produced through Save To will print on their
- * own. Also includes the preview data as a comment when
- * specified.
- */
- - endHeaderComments
- {
- DPSContext ctxt;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- ctxt = DPSGetCurrentContext();
- DPSPrintf(ctxt, "%%%%EndComments\n\n");
-
- DPSPrintf(ctxt, "%%%%BeginProcSet: EPSF_Illustrator_abbrev 0 0\n");
- WriteEpsfProcSetDef ();
- DPSPrintf(ctxt, "%%%%EndProcSet\n\n");
-
- if (imageId && [[SaveAsPanel new] format] == SAVE_EPSPREVIEW)
- WriteEpsfPreview(imageId);
- }
- else
- [super endHeaderComments];
-
- return self;
- }
-
- /*
- * If saving in illustrator, override the prologue comment.
- */
- - endPrologue
- {
- DPSContext ctxt;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- ctxt = DPSGetCurrentContext();
- DPSPrintf(ctxt, "%%%%EndProlog\n\n");
- }
- else
- [super endPrologue];
-
- return self;
- }
-
- /* Initialize the Illustrator abbreviated proc set. */
- - beginSetup
- {
- DPSContext ctxt;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- ctxt = DPSGetCurrentContext();
- DPSPrintf(ctxt, "%%%%BeginSetup\n");
- WriteEpsfProcSetInit();
- }
- else
- [super beginSetup];
-
- return self;
- }
-
- - endSetup
- {
- DPSContext ctxt;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- ctxt = DPSGetCurrentContext();
- DPSPrintf(ctxt, "%%%%EndSetup\n");
- }
- else
- [super endSetup];
-
- return self;
- }
-
- /* Terminate the Illustrator abbreviated proc set. */
- - beginTrailer
- {
- DPSContext ctxt;
-
- if (NXDrawingStatus == NX_COPYING)
- {
- ctxt = DPSGetCurrentContext();
- DPSPrintf(ctxt, "%%%%Trailer\n");
- WriteEpsfProcSetTerm();
- }
- else
- [super beginTrailer];
-
- return self;
- }
-
- - endTrailer
- {
- if (NXDrawingStatus != NX_COPYING)
- [super endTrailer];
-
- return self;
- }
-
- @end
-